package org.t2.game.server.module.mail.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.gaming.prefab.mail.IMailTemplateDesign;
import org.gaming.prefab.mail.IMailTemplateEnum;
import org.gaming.prefab.mail.MailAbstractService;
import org.gaming.prefab.mail.MailArgs;
import org.gaming.prefab.thing.NoticeType;
import org.gaming.ruler.eventbus.Subscribe;
import org.gaming.service.repository.IRepository;
import org.gaming.service.repository.Repository;
import org.gaming.tool.DateTimeUtil;
import org.gaming.tool.GsonUtil;
import org.gaming.tool.LocalDateTimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.t2.design.module.EveryDayTable;
import org.t2.design.module.autogen.EveryDayAbstractTable.EveryDayCfg;
import org.t2.design.struct.RewardThing;
import org.t2.game.server.foundation.player.PlayerContextManager;
import org.t2.game.server.module.mail.constant.MailText;
import org.t2.game.server.module.mail.model.Mail;
import org.t2.game.server.module.mail.model.MailPlayer;
import org.t2.game.server.module.player.event.PlayerCreateEvent;
import org.t2.game.server.module.player.event.PlayerLoginEvent;
import org.t2.game.server.module.tips.GameCause;

import pb.t2.protobuf.mail.Mail.MailPushMessage;
import pb.t2.protobuf.mail.Mail.PbMail;
import pb.t2.protobuf.ministruct.MiniStruct.PbReward;

/**
 * @author yh
 * @date 2023/5/31
 * @apiNote
 */

@Service
public class MailService extends MailAbstractService<Mail> {
    @Autowired
    private PlayerContextManager playerContextManager;
    @Autowired
    private MailLogger mailLogger;
    @Autowired
    private MailSystemService mailSystemService;
    @Autowired
    private MailConverter mailConverter;
    @Autowired
    private MailPlayerService mailPlayerService;
    
    private IRepository<Mail> repository;
    protected IRepository<Mail> repository() {
        if (repository == null) {
            repository = Repository.get(Mail.class);
        }
        return repository;
    }

    @Override
    public List<Mail> mails(long entityId) {
        List<Mail> newMails = mailSystemService.pullMailFromSystem(entityId);
        if (!newMails.isEmpty()) {
            repository().insertAll(newMails);
        }
        return repository().listByKeys(entityId);
    }

    public Mail getMail(long entityId, long mailId) {
        return repository().getByKeys(entityId, mailId);
    }

    @Override
    protected Mail createMail(long receiver) {
        return new Mail();
    }

    @Override
    protected List<String> convertArgs(List<String> formatRules, MailArgs mailArgs) {
       return mailConverter.changerArgs(formatRules, mailArgs.getArgs());
    }

    @Override
    public void insert(List<Mail> mails) {
        repository().insertAll(mails);
    }

    public void insert(Mail mail) {
        repository().insert(mail);
    }

    @Override
    public void update(List<Mail> mails) {
        repository().updateAll(mails);
    }

    public void update(Mail mail) {
        repository().update(mail);
    }

    @Override
    public void delete(List<Mail> mails) {
        repository().deleteAll(mails);
        mailLogger.logOnDelete(mails);
    }

    /**
     * 发邮
     */
    public void sendMail(Mail mail, NoticeType noticeType) {
        this.insert(mail);
        if (noticeType != NoticeType.SLIENT) {
            playerContextManager.push(mail.getReceiver(), MailPushMessage.Proto.ID, MailPushMessage.getDefaultInstance());
        }
    }

    public void sendMail(List<Mail> mails, NoticeType noticeType) {
        this.insert(mails);
        if (noticeType != NoticeType.SLIENT) {
            for (Mail mail : mails) {
            	if(!playerContextManager.isOnline(mail.getReceiver())) {
            		continue;
            	}
                playerContextManager.push(mail.getReceiver(), MailPushMessage.Proto.ID, MailPushMessage.getDefaultInstance());
            }
        }
    }

    public PbMail build(Mail mail) {
    	PbMail.Builder builder = PbMail.newBuilder();
        builder.setId(mail.getId());
        if(!mail.getTitleArgs().isEmpty()) {
        	builder.setTitle(mail.getTitleArgs().get(0));
        }
        if(!mail.getContentArgs().isEmpty()) {
        	builder.setContent(mail.getContentArgs().get(0));
        }
        String attachment = mail.getAttachment();
        List<RewardThing> rewardThings = GsonUtil.getList(attachment, RewardThing.class);
        for (RewardThing rewardThing : rewardThings) {
        	PbReward.Builder pbReward = PbReward.newBuilder();
        	pbReward.setId(rewardThing.getThingId());
        	pbReward.setNum(rewardThing.getNumber());
            builder.addRewards(pbReward.build());
        }
        builder.setRead(mail.isRead());
        builder.setReceive(mail.isReceive());
        builder.setExpireTime(mail.getExpireTime());
        builder.setReceTime(LocalDateTimeUtil.toEpochMilli(mail.getInsertTime()));
        return builder.build();
    }

	@Override
	protected IMailTemplateDesign getTemplate(IMailTemplateEnum templateEnum) {
		IMailTemplateDesign design = new IMailTemplateDesign() {
			@Override
			public int getTemplateId() {
				return 1;
			}

			@Override
			public List<String> getTitleFormatRules() {
				return Collections.emptyList();
			}

			@Override
			public List<String> getContentFormatRules() {
				return Collections.emptyList();
			}

			@Override
			public int getExpireDay() {
				return 30;
			}
    	};
    	return design;
	}
	
	public Mail newMail(long playerId, String title, String content, List<RewardThing> rewardList, GameCause gameCause) {
		Mail mail = new Mail();
    	mail.setReceiver(playerId);
        mail.setTemplate(0);
        mail.markUnread();
        mail.markUnreceive();
        mail.setGameCause(gameCause.getCode());
        mail.setGameCauseText(gameCause.getDesc());
        
        mail.getTitleArgs().add(title);
        mail.getContentArgs().add(content);
        mail.setAttachment(GsonUtil.toJson(rewardList));
        mail.setExpireTime(DateTimeUtil.currMillis() + DateTimeUtil.ONE_DAY_MILLIS * 30);
        mail.setFromPoolId(0);
        return mail;
	}
	
	@Subscribe
	private void listen(PlayerLoginEvent event) {
		MailPlayer entity = mailPlayerService.getEntity(event.getPlayer().getId());
		if(entity.isSendDailyReward()) {
			return;
		}
		
		entity.setSendDailyReward(true);
		mailPlayerService.update(entity);
		
		List<Mail> mails = new ArrayList<>();
		for(EveryDayCfg everyDayCfg : EveryDayTable.ins().all()) {
			Mail mail = this.newMail(event.getPlayer().getId(), MailText.Mail1003Title, MailText.Mail1003Content,
					everyDayCfg.getReward(), GameCause.MAIL_DAILY_REWARD);
			mails.add(mail);
		}
		this.sendMail(mails, NoticeType.SLIENT);
	}
	
	@Subscribe
	private void listen(PlayerCreateEvent event) {
		MailPlayer entity = mailPlayerService.getEntity(event.getPlayer().getId());
		if(entity.isSendDailyReward()) {
			return;
		}
		
		entity.setSendDailyReward(true);
		mailPlayerService.update(entity);
		
		List<Mail> mails = new ArrayList<>();
		for(EveryDayCfg everyDayCfg : EveryDayTable.ins().all()) {
			Mail mail = this.newMail(event.getPlayer().getId(), MailText.Mail1003Title, MailText.Mail1003Content,
					everyDayCfg.getReward(), GameCause.MAIL_DAILY_REWARD);
			mails.add(mail);
		}
		this.sendMail(mails, NoticeType.SLIENT);
	}
}
